#include "NetworkServer.hpp"
#include <nlohmann/json.hpp>
#include <spdlog/spdlog.h>
#include <algorithm>
#include <msgpack.hpp>
#include <iostream>
#include <cstring>
#include <chrono>
#include <sstream>
#include <fmt/format.h>

NetworkServer::NetworkServer()
{
  CROW_ROUTE(app,"/hello")([this](){return crow::status::OK;});
  CROW_ROUTE(app,"/createTask")([this](const crow::request& req){
    char* name=req.url_params.get("name");
    if(name==nullptr)
      return crow::response(crow::status::BAD_REQUEST);
    msgpack::sbuffer buf;
    msgpack::pack(buf,funcCreateTask(name));
    return crow::response(std::string(buf.data(),buf.size()));
  });
  CROW_ROUTE(app,"/checkStuExist")([this](const crow::request& req){
    char* id=req.url_params.get("id");
    if(id==nullptr)
      return crow::response(crow::status::BAD_REQUEST);
    msgpack::sbuffer buf;
    msgpack::pack(buf,funcCheckStuExists(std::atoi(id)));
    return crow::response(std::string(buf.data(),buf.size()));
  });
  CROW_ROUTE(app,"/getStuInf")([this](const crow::request& req){
    char* id=req.url_params.get("id");
    if(id==nullptr)
      return crow::response(crow::status::BAD_REQUEST);
    msgpack::sbuffer buf;
    msgpack::pack(buf,funcGetStudentInf(std::atoi(id)));
    return crow::response(std::string(buf.data(),buf.size()));
  });
  CROW_ROUTE(app,"/startShot")([this](const crow::request& req){
    char* taskid=req.url_params.get("taskid");
    char* stuid=req.url_params.get("stuid");
    if(taskid==nullptr || stuid==nullptr)
      return crow::response(crow::status::BAD_REQUEST);
    funcStartRecord(std::stoi(taskid),std::stoi(stuid));
    return crow::response(crow::status::OK);
  });
  CROW_ROUTE(app,"/stopShot")([this](const crow::request& req){
    funcStopRecord();
    return crow::response(crow::status::OK);
  });
  CROW_ROUTE(app,"/CheckShotStatus")([this](const crow::request& req){
    msgpack::sbuffer buf;
    msgpack::pack(buf,funcGetRecordStatus());
    return crow::response(std::string(buf.data(),buf.size()));
  });
  CROW_WEBSOCKET_ROUTE(app,"/wsConnStatus")
    .onaccept([this](const crow::request& req,void** userdata){
      return TerminalConnect==nullptr;
    })
    .onopen([this](crow::websocket::connection& conn){
      TerminalConnect=&conn;
      funcTerminalConnectChange(true);
    })
    .onclose([this](crow::websocket::connection& conn,const std::string& reason){
      TerminalConnect=nullptr;
      funcTerminalConnectChange(false);
    })
    ;
  crow::logger::setHandler(&logProxy);
}

NetworkServer::~NetworkServer()
{
  app.stop();
  netWorkThread.join();
}

void NetworkServer::Boot()
{
  netWorkThread=std::thread(&NetworkServer::netWorkFunc,this);
}

void NetworkServer::netWorkFunc()
{
  app.bindaddr("0.0.0.0").port(10090).multithreaded().run();
}

void networkServer_LogProxy::log(std::string message,crow::LogLevel level)
{
  switch(level)
  {
    case crow::LogLevel::INFO:
      spdlog::info("NetworkServer: {}",message);
      break;
    case crow::LogLevel::DEBUG:
      spdlog::debug("NetworkServer: {}",message);
      break;
    case crow::LogLevel::ERROR:
      spdlog::error("NetworkServer: {}",message);
      break;
    case crow::LogLevel::WARNING:
      spdlog::warn("NetworkServer: {}",message);
      break;
    case crow::LogLevel::CRITICAL:
      spdlog::info("NetworkServer: {}",message);
      break;
  }
}

